home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / utils / newmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-06  |  25.1 KB  |  925 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: newmail.c,v 5.18 1993/06/06 18:00:10 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.18 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1988-1992 USENET Community Trust
  8.  *             Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: newmail.c,v $
  17.  * Revision 5.18  1993/06/06  18:00:10  syd
  18.  * Fix max folder check, off by one
  19.  *
  20.  * Revision 5.17  1993/04/21  01:18:27  syd
  21.  * newmail treated a line with From_ preceeded by whitespace as a valid
  22.  * message delimiter.
  23.  * From: Jan Djarv <Jan.Djarv@sa.erisoft.se>
  24.  *
  25.  * Revision 5.16  1993/04/12  03:51:42  syd
  26.  * prevent double spacing in newmail
  27.  * From: Syd
  28.  *
  29.  * Revision 5.15  1993/04/12  03:40:28  syd
  30.  * Some OSs need the time.h includes
  31.  * From: ebd@fang.att.com (Elliot B Dierksen)
  32.  *
  33.  * Revision 5.14  1993/02/09  19:03:15  syd
  34.  * add isspace macro from ctype.h include
  35.  *
  36.  * Revision 5.13  1993/02/03  16:10:31  syd
  37.  * More utime portability problems with convex
  38.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  39.  *
  40.  * Revision 5.12  1993/01/27  21:00:30  syd
  41.  * When newmail stats/reads the mailbox it updates the access times.  This
  42.  * causes problems for users that run both newmail and xbiff since xbiff
  43.  * just looks at the access times of the mailbox.  Added code to newmail
  44.  * that borrows some code from src/leavembox.c for updating mailbox access
  45.  * times.
  46.  * From: aj@redwood.cray.com (Chris Jackman)
  47.  *
  48.  * Revision 5.11  1993/01/27  20:49:40  syd
  49.  * It seams that SCO Unix nedds 1 pair of () extra to get
  50.  * the new newmail.c code to work.
  51.  * From: Jan S{ll <jan%unikla@Mail.SWIP.net>
  52.  *
  53.  * Revision 5.10  1993/01/27  20:44:27  syd
  54.  * Correct MMDF syntax problems and newmail botches.
  55.  * From: chip@chinacat.unicom.com (Chip Rosenthal)
  56.  *
  57.  * Revision 5.9  1993/01/19  05:07:05  syd
  58.  * Trim erroreous extra log entry
  59.  * From: Syd
  60.  *
  61.  * Significant changes to provide consistent Date and From_ header
  62.  * cracking.  Overhauled date utilities and moved into library.  Moved
  63.  * real_from() into library.  Modified frm, newmail, and readmsg utilities
  64.  * to use library version of real_from().  Moved get_word() from Elm
  65.  * source into library.  Added new library routines atonum() and strfcpy().
  66.  * Fixed trailing backslash bug in len_next().
  67.  * From: chip@chinacat.unicom.com (Chip Rosenthal)
  68.  *
  69.  * Revision 5.7  1992/12/11  01:45:04  syd
  70.  * remove sys/types.h include, it is now included by defs.h
  71.  * and this routine includes defs.h or indirectly includes defs.h
  72.  * From: Syd
  73.  *
  74.  * Revision 5.6  1992/11/17  19:23:28  syd
  75.  * add blank after priority to
  76.  *
  77.  * Revision 5.5  1992/11/07  20:05:52  syd
  78.  * change to use header_cmp to allow for linear white space around the colon
  79.  * From: Syd
  80.  *
  81.  * Revision 5.4  1992/10/27  01:43:40  syd
  82.  * Move posix_signal to lib directory
  83.  * From: tom@osf.org
  84.  *
  85.  * Revision 5.3  1992/10/25  02:54:00  syd
  86.  * add posix signal stuff as stop gap, needs to be moved to lib
  87.  * From: syd
  88.  *
  89.  * Revision 5.2  1992/10/24  13:11:42  syd
  90.  * fix newmail attempting to close a file descriptor even if the corresponding
  91.  * open failed.
  92.  * From: "Peter A. Bigot" <pab@cs.arizona.edu>
  93.  *
  94.  * Revision 5.1  1992/10/04  00:46:45  syd
  95.  * Initial checkin as of 2.4 Release at PL0
  96.  *
  97.  *
  98.  ******************************************************************************/
  99.  
  100. /** This is actually two programs folded into one - 'newmail()' and
  101.     'wnewmail()'.  They perform essentially the same function, to
  102.     monitor the mail arriving in a set of/a mailbox or folder, but
  103.     newmail is designed to run in background on a terminal, and
  104.     wnewmail is designed to have a window of its own to run in.
  105.  
  106.     The main difference is that wnewmail checks for mail more often.
  107.  
  108.     The usage parameters are:
  109.  
  110.     -i <interval>          how often to check for mail
  111.                 (default: 60 secs if newmail,
  112.                       10 secs if wnewmail)
  113.  
  114.     <filename>        name of a folder to monitor
  115.                 (can prefix with '+'/'=', or can
  116.                  default to the incoming mailbox)
  117.  
  118.     <filename>=prefix    file to monitor, output with specified
  119.                 prefix when mail arrives.
  120.  
  121.     If we're monitoring more than one mailbox the program will prefix
  122.     each line output (if 'newmail') or each cluster of mail (if 'wnewmail')
  123.     with the basename of the folder the mail has arrived in.  In the 
  124.     interest of exhaustive functionality, you can also use the "=prefix"
  125.     suffix (eh?) to specify your own strings to prefix messages with.
  126.  
  127.     The output format is either:
  128.  
  129.       newmail:
  130.          >> New mail from <user> - <subject>
  131.          >> Priority mail from <user> - <subject>
  132.  
  133.          >> <folder>: from <user> - <subject>
  134.          >> <folder>: Priority from <user> - <subject>
  135.  
  136.       wnewmail:
  137.          <user> - <subject>
  138.          Priority: <user> - <subject>
  139.  
  140.          <folder>: <user> - <subject>
  141.          <folder>: Priority: <user> - <subject>\fR
  142.  
  143. **/
  144.  
  145. #include "elmutil.h"
  146. #include <ctype.h>
  147. #include "s_newmail.h"
  148.  
  149. #ifdef PWDINSYS
  150. #  include <sys/pwd.h>
  151. #else
  152. #  include <pwd.h>
  153. #endif
  154. #include <sys/stat.h>
  155.  
  156. #ifdef I_TIME
  157. #  include <time.h>
  158. #endif
  159. #ifdef I_SYSTIME
  160. #  include <sys/time.h>
  161. #endif
  162. #ifdef BSD
  163. #  include <sys/timeb.h>
  164. #endif
  165.  
  166. #ifdef I_UTIME
  167. #  include <utime.h>
  168. #endif
  169. #ifdef I_SYSUTIME
  170. #  include <sys/utime.h>
  171. #endif
  172.  
  173.  
  174. /**********
  175.    Since a number of machines don't seem to bother to define the utimbuf
  176.    structure for some *very* obscure reason.... 
  177.  
  178.    Suprise, though, BSD has a different utime() entirely...*sigh*
  179. **********/
  180.  
  181. #ifndef BSD
  182. # ifndef UTIMBUF
  183.  
  184. struct utimbuf {
  185.         time_t  actime;         /** access time       **/ 
  186.         time_t  modtime;        /** modification time **/
  187.        };
  188.  
  189. # endif /* UTIMBUF */
  190. #endif /* BSD */
  191.  
  192.  
  193. #define LINEFEED        (char) 10
  194. #define BEGINNING        0            /* seek fseek(3S) */
  195. #define DEFAULT_INTERVAL    60
  196.  
  197. #define MAX_FOLDERS        25        /* max we can keep track of */
  198.  
  199. /*
  200.  * The "read_headers()" and "show_header()" routines use a (struct header_rec)
  201.  * to hold the header information.  This structure does not have a flag to
  202.  * save the message priority status.  We don't need the "encrypted" flag in
  203.  * the structure, so we will use that instead.
  204.  */
  205. #define priority encrypted
  206.  
  207. #define metachar(c)    (c == '+' || c == '=' || c == '%')
  208.  
  209. char  *getusername();
  210. long  bytes();
  211.  
  212. struct folder_struct {
  213.       char        foldername[SLEN];
  214.       char        prefix[NLEN];
  215.       long        filesize;
  216.       int        access_error;
  217.        } folders[MAX_FOLDERS] = {0};
  218.  
  219. int  interval_time,        /* how long to sleep between checks */
  220.      debug = 0,            /* include verbose debug output?    */
  221.      in_window = 0,        /* are we running as 'wnewmail'?    */
  222.      total_folders = 0,        /* # of folders we're monitoring    */
  223.      print_prefix = 0,        /* force printing of prefix        */
  224.      current_folder = 0;    /* struct pointer for looping       */
  225. FILE    *fd = NULL;        /* fd to use to read folders        */
  226. FILE    *debugfile = stderr;
  227.  
  228. #ifdef PIDCHECK
  229. int  parent_pid;        /* See if sucide should be attempt  */
  230. #endif /* PIDCHECK */
  231.  
  232. extern int errno;
  233.  
  234. #if defined(BSD) && !defined(__convex__)
  235.         time_t utime_buffer[2];         /* utime command */
  236. #else
  237.         struct utimbuf utime_buffer;    /* utime command */
  238. #endif
  239.  
  240. static char    *no_subj,    /* Pointer to No subject text    */
  241.         *priority_to,    /* pointer to Priority to text    */
  242.         *priority_text,    /* pointer to priority text    */
  243.         *To_text,    /* pointer To to text        */
  244.         *priority_mail,    /* pointer to priority mail    */
  245.         *mail_text,    /* pointer to mail text        */
  246.         *to_text,    /* pointer to to text        */
  247.         *from_text;    /* pointer to from text        */
  248.  
  249. main(argc, argv)
  250. int argc;
  251. char *argv[];
  252. {
  253.     extern char *optarg;
  254.     extern int   optind;
  255.     char *ptr;
  256.     int c, i, done;
  257.     long lastsize,
  258.          newsize;            /* file size for comparison..      */
  259.     register struct folder_struct *cur_folder;
  260.     int hostlen, domlen;
  261.     struct passwd *pass;
  262. #ifndef    _POSIX_SOURCE
  263.     struct passwd *getpwuid();
  264. #endif
  265.  
  266. #ifdef I_LOCALE
  267.     setlocale(LC_ALL, "");
  268. #endif
  269.  
  270.     elm_msg_cat = catopen("elm2.4", 0);
  271.  
  272.     /* Get the No subject string */
  273.  
  274.     no_subj = catgets(elm_msg_cat, NewmailSet, NewmailNoSubject,
  275.        "(No Subject Specified)");
  276.     priority_to = catgets(elm_msg_cat, NewmailSet,
  277.        NewmailInWinPriorityTo, "Priority to ");
  278.     priority_text = catgets(elm_msg_cat, NewmailSet,
  279.           NewmailInWinPriority, "Priority ");
  280.     To_text = catgets(elm_msg_cat, NewmailSet, NewmailInWinTo, "To ");
  281.     priority_mail = catgets(elm_msg_cat, NewmailSet,
  282.        NewmailPriorityMail, "Priority mail ");
  283.     mail_text = catgets(elm_msg_cat, NewmailSet, NewmailMail, "Mail ");
  284.     to_text = catgets(elm_msg_cat, NewmailSet, NewmailTo, "to ");
  285.     from_text = catgets(elm_msg_cat, NewmailSet, NewmailFrom, "from ");
  286.  
  287. #ifdef HOSTCOMPILED
  288.     strncpy(hostname, HOSTNAME, sizeof(hostname) - 1);
  289.     hostname[sizeof(hostname) - 1] = '\0';
  290. #else
  291.     gethostname(hostname, sizeof(hostname));
  292. #endif
  293.     gethostdomain(hostdomain, sizeof(hostdomain));
  294.  
  295.     /*
  296.      * see init.c for an explanation of this!
  297.      */
  298.     hostlen = strlen(hostname);
  299.     domlen = strlen(hostdomain);
  300.     if (hostlen >= domlen) {
  301.       if (istrcmp(&hostname[hostlen - domlen], hostdomain) == 0)
  302.         strcpy(hostfullname, hostname);
  303.       else {
  304.         strcpy(hostfullname, hostname);
  305.         strcat(hostfullname, hostdomain);
  306.       }
  307.     } else {
  308.       if (istrcmp(hostname, hostdomain + 1) == 0)
  309.         strcpy(hostfullname, hostname);
  310.       else {
  311.         strcpy(hostfullname, hostname);
  312.         strcat(hostfullname, hostdomain);
  313.       }
  314.     }
  315.  
  316.     /*
  317.      * get user name and full user name so we know who we are
  318.      */
  319.     if((pass = getpwuid(getuid())) == NULL) {
  320.       fprintf(stderr, catgets(elm_msg_cat, NewmailSet, NewmailNoPasswdEntry,
  321.           "You have no password entry!"));
  322.       exit(1);
  323.     }
  324.     strcpy(username, pass->pw_name);
  325.  
  326.     if((ptr = get_full_name(username)) != NULL)
  327.       strcpy(full_username, ptr);
  328.     else
  329.       strcpy(full_username, username);
  330.  
  331. #ifdef PIDCHECK                /* This will get the pid that         */
  332.     parent_pid = getppid();        /* started the program, ie: /bin/sh   */
  333.                     /* If it dies for some reason (logout)*/
  334. #endif /* PIDCHECK */            /* Then exit the program if PIDCHECK  */
  335.  
  336.     interval_time = DEFAULT_INTERVAL;
  337.  
  338.     /** let's see if the first character of the basename of the
  339.         command invoked is a 'w' (e.g. have we been called as
  340.         'wnewmail' rather than just 'newmail'?)
  341.     **/
  342.  
  343.     for (i=0, ptr=(argv[0] + strlen(argv[0])-1); !i && ptr > argv[0]; ptr--)
  344.       if (*ptr == '/') {
  345.         in_window = (*(ptr+1) == 'w');
  346.         i++;
  347.       }
  348.  
  349.     if (ptr == argv[0] && i == 0 && argv[0][0] == 'w')
  350.       in_window = 1;
  351.  
  352.     while ((c = getopt(argc, argv, "di:w")) != EOF) {
  353.       switch (c) {
  354.         case 'd' : debug++;                    break;
  355.         case 'i' : interval_time = atoi(optarg);        break;
  356.         case 'w' : in_window = 1;                break;
  357.         default  : usage(argv[0]);                exit(1);
  358.      }
  359.     }
  360.  
  361.     if (interval_time < 10)
  362.       if (interval_time == 1)
  363.         fprintf(stderr, catgets(elm_msg_cat, NewmailSet, NewmailShort,
  364. "Warning: interval set to 1 second.  I hope you know what you're doing!\n"));
  365.       else
  366.         fprintf(stderr, catgets(elm_msg_cat, NewmailSet, NewmailShortPlur,
  367. "Warning: interval set to %d seconds.  I hope you know what you're doing!\n"),
  368.         interval_time);
  369.  
  370.     /* now let's parse the foldernames, if any are given */
  371.  
  372.     if (optind >= argc) /* get default */
  373.       add_default_folder();
  374.     else {
  375.       while (optind < argc)
  376.         add_folder(argv[optind++]);
  377.       pad_prefixes();            /* for nice output...*/
  378.     }
  379.     if (total_folders > 1)
  380.         print_prefix = 1;
  381.  
  382. #ifdef AUTO_BACKGROUND
  383.     if (! in_window) {
  384.       if (fork())        /* automatically puts this task in background! */
  385.         exit(0);
  386.  
  387.       (void) signal(SIGINT, SIG_IGN);
  388.       (void) signal(SIGQUIT, SIG_IGN);
  389.     }
  390. #endif
  391.     (void) signal(SIGHUP, SIG_DFL);
  392.  
  393.     if (in_window && ! debug)
  394.       printf(catgets(elm_msg_cat, NewmailSet, NewmailIncommingMail,
  395.           "Incoming mail:\n"));
  396.  
  397.     while (1) {
  398.  
  399. #ifdef PIDCHECK
  400.     if ( kill(parent_pid,0))
  401.         exit(0);
  402. #else
  403. #ifndef AUTO_BACKGROUND        /* won't work if we're nested this deep! */
  404.       if (getppid() == 1)     /* we've lost our shell! */
  405.         exit(0);
  406. #endif /* AUTO_BACKGROUND */
  407. #endif /* PIDCHECK */
  408.  
  409.       if (! isatty(1))    /* we're not sending output to a tty any more */
  410.          exit(0);
  411.  
  412.       dprint(1, (debugfile, "\n----\n"));
  413.  
  414.       for (i = 0; i < total_folders; i++) {
  415.  
  416.         cur_folder = &folders[i];
  417.         dprint(1, (debugfile, "[checking folder #%d: %s]\n",
  418.         i, cur_folder->foldername));
  419.  
  420.         if ((newsize = bytes(cur_folder->foldername)) == 
  421.             cur_folder->filesize)     /* no new mail has arrived! */
  422.             continue;
  423.  
  424.         if ((fd = fopen(cur_folder->foldername,"r")) == NULL) {
  425.           if (errno == EACCES) {
  426.         cur_folder->access_error++;
  427.         if (cur_folder->access_error > 5) {
  428.           fprintf(stderr, catgets(elm_msg_cat, NewmailSet,
  429.               NewmailErrNoPerm,
  430.               "\nPermission to monitor \"%s\" denied!\n\n"),
  431.              cur_folder->foldername);
  432.           sleep(5);
  433.           exit(1);
  434.         }
  435.           }
  436.           continue;
  437.         }
  438.  
  439.         if ((newsize = bytes(cur_folder->foldername)) > 
  440.             cur_folder->filesize) {    /* new mail has arrived! */
  441.  
  442.           dprint(1, (debugfile,
  443.           "\tnew mail has arrived!  old size = %ld, new size=%ld\n",
  444.           cur_folder->filesize, newsize));
  445.  
  446.           /* skip what we've read already... */
  447.  
  448.           if (fseek(fd, cur_folder->filesize, 
  449.             BEGINNING) != 0)
  450.             perror("fseek()");
  451.  
  452.           cur_folder->filesize = newsize;
  453.  
  454.           /* read and display new mail! */
  455.           if (read_headers(cur_folder) && ! in_window)
  456.             printf("\n\r");
  457.           /* try to set the file access times back, ignore
  458.          failures */
  459.  
  460. #if defined(BSD) && !defined(__convex__)
  461.           utime(cur_folder->foldername, utime_buffer);
  462. #else
  463.               utime(cur_folder->foldername, &utime_buffer);
  464. #endif
  465.         }
  466.         else {    /* file SHRUNK! */
  467.  
  468.           cur_folder->filesize = bytes(cur_folder->foldername);
  469.           lastsize = cur_folder->filesize;
  470.           done     = 0;
  471.  
  472.           while (! done) {
  473.             sleep(1);    /* wait for the size to stabilize */
  474.             newsize = bytes(cur_folder->foldername);
  475.             if (newsize != lastsize)
  476.               lastsize = newsize;
  477.         else
  478.               done++;
  479.           } 
  480.             
  481.           cur_folder->filesize = newsize;
  482.         }
  483.         (void) fclose(fd);            /* close it and ...         */
  484.       }
  485.  
  486.       sleep(interval_time);
  487.     }
  488. }
  489.  
  490. int
  491. read_headers(cur_folder)
  492. register struct folder_struct *cur_folder;
  493. {
  494.     /** read the headers, output as found given current_folder,
  495.         the prefix of that folder, and whether we're in a window
  496.         or not.
  497.     **/
  498.  
  499.     struct header_rec hdr;        /* holds header info on curr mssg */
  500.     char buffer[SLEN];        /* message line buffer          */
  501.     char *fld_name, *fld_val;    /* field name and value pointers  */
  502.     register int in_header;        /* TRUE when processing a hdr      */
  503.     int count;            /* count of messages done      */
  504.     int init_header;        /* TRUE to reset hdr for new mssg */
  505. #ifdef MMDF
  506.     int newheader = 0;        /* count lead/trail ^A^A^A^A      */
  507. #endif /* MMDF */
  508.  
  509.     count = 0;
  510.     init_header = TRUE;
  511.  
  512.     /*
  513.      * Go through every line of the mailbox.
  514.      */
  515.     while (mail_gets(buffer, SLEN, fd) != 0) {
  516.  
  517.       /*
  518.        * Initialize header record for a new message.
  519.        */
  520.       if (init_header) {
  521.         hdr.to[0] = '\0';
  522.         hdr.from[0] = '\0';
  523.         hdr.subject[0] = '\0';
  524.         hdr.priority = FALSE;
  525.         in_header = FALSE;
  526.         init_header = FALSE;
  527.       }
  528.  
  529.       /*
  530.        * Search for the start of a message.
  531.        */
  532.       if (!in_header) {
  533.         in_header = 
  534. #ifdef MMDF
  535.           (strcmp(buffer, MSG_SEPARATOR) == 0 && (newheader = !newheader));
  536. #else
  537.           first_word(buffer, "From ") && real_from(buffer, &hdr);
  538. #endif /* MMDF */
  539.         continue;
  540.       }
  541.  
  542.       /*
  543.        * Look for blank line at the end of the message header.
  544.        */
  545.       if (buffer[0] == LINEFEED) {
  546.         count++;
  547.         show_header(&hdr, cur_folder);
  548.         init_header = TRUE;
  549.         continue;
  550.       }
  551.  
  552. #ifdef MMDF
  553.       /*
  554.        * With MMDF we still need to locate the "From_" header.
  555.        */
  556.       if (real_from(buffer, &hdr))
  557.         continue;
  558. #endif /* MMDF */
  559.  
  560.       if (header_cmp(buffer, "From", (char *) NULL))  {
  561.         parse_arpa_who(buffer, hdr.from, 0);
  562.         continue;
  563.       }
  564.  
  565.       /*
  566.        * Split up the header into a field name and field value.
  567.        */
  568.       fld_name = fld_val = buffer;
  569.       while (*fld_val != '\0' && !isspace(*fld_val))
  570.         ++fld_val;
  571.       if (*fld_val != '\0') {
  572.         *fld_val = '\0';
  573.         do {
  574.           ++fld_val;
  575.         } while (isspace(*fld_val));
  576.       }
  577.  
  578.       if (istrcmp(fld_name, ">From") == 0) {
  579.         forwarded(fld_val, hdr.from);
  580.         continue;
  581.       }
  582.  
  583.       if (istrcmp(fld_name, "To:") == 0) {
  584.         figure_out_addressee(fld_val, hdr.to);
  585.         continue;
  586.       }
  587.  
  588.       if (istrcmp(fld_name, "Subject:") == 0) {
  589.         strfcpy(hdr.subject, fld_val, sizeof(hdr.subject));
  590.         continue;
  591.       }
  592.  
  593.       if (istrcmp(fld_name, "Re:") == 0) {
  594.         if (hdr.subject[0] == '\0')
  595.           strfcpy(hdr.subject, fld_val, sizeof(hdr.subject));
  596.         continue;
  597.       }
  598.  
  599.       if (istrcmp(fld_name, "Importance:") == 0) {
  600.         if (atoi(fld_val) >= 2)
  601.           hdr.priority = TRUE;
  602.         continue;
  603.       }
  604.  
  605.       if (istrcmp(fld_name, "Priority:") == 0) {
  606.         if (strincmp(fld_val, "normal", 6) != 0 &&
  607.                 strincmp(fld_val, "non-urgent", 10) != 0)
  608.           hdr.priority = TRUE;
  609.         continue;
  610.       }
  611.  
  612.       /*
  613.        * If we reach this point, it must be an unknown
  614.        * or boring header.  Skip it.
  615.        */
  616.  
  617.     }
  618.  
  619.     return(count);
  620. }
  621.  
  622. add_folder(name)
  623. char *name;
  624. {
  625.     /* add the specified folder to the list of folders...ignore any
  626.        problems we may having finding it (user could be monitoring
  627.        a mailbox that doesn't currently exist, for example)
  628.     */
  629.  
  630.     char *cp, buf[SLEN];
  631.  
  632.     if (current_folder >= MAX_FOLDERS) {
  633.       fprintf(stderr, catgets(elm_msg_cat, NewmailSet, NewmailErrMaxFolders,
  634.             "Sorry, but I can only keep track of %d folders.\n"), MAX_FOLDERS);
  635.       exit(1);
  636.     }
  637.  
  638.     /* now let's rip off the suffix "=<string>" if it's there... */
  639.  
  640.     for (cp = name + strlen(name); cp > name+1 && *cp != '=' ; cp--)
  641.       /* just keep stepping backwards */ ;
  642.  
  643.     /* if *cp isn't pointing to the first character we'e got something! */
  644.  
  645.     if (cp > name+1) {
  646.  
  647.       *cp++ = '\0';        /* null terminate the filename & get prefix */
  648.  
  649.       if (metachar(*cp)) cp++;
  650.  
  651.       strcpy(folders[current_folder].prefix, cp);
  652.       print_prefix = 1;
  653.     }
  654.     else {            /* nope, let's get the basename of the file */
  655.       for (cp = name + strlen(name); cp > name && *cp != '/'; cp--)
  656.         /* backing up a bit... */ ;
  657.  
  658.       if (metachar(*cp)) cp++;
  659.       if (*cp == '/') cp++;
  660.  
  661.       strcpy(folders[current_folder].prefix, cp);
  662.     }
  663.  
  664.     /* and next let's see what kind of weird prefix chars this user
  665.        might be testing us with.  We can have '+'|'='|'%' to expand
  666.        or a file located in the incoming mail dir...
  667.     */
  668.  
  669.     if (metachar(name[0]))
  670.       expand_filename(name, folders[current_folder].foldername);
  671.     else if (access(name, 00) == -1) {
  672.       /* let's try it in the mail home directory */
  673.       sprintf(buf, "%s%s", mailhome, name);
  674.       if (access(buf, 00) != -1)         /* aha! */
  675.         strcpy(folders[current_folder].foldername, buf);
  676.       else
  677.         strcpy(folders[current_folder].foldername, name);
  678.     }
  679.     else
  680.       strcpy(folders[current_folder].foldername, name);
  681.  
  682.     /* now let's try to actually open the file descriptor and grab
  683.        a size... */
  684.  
  685.     if ((fd = fopen(folders[current_folder].foldername, "r")) == NULL)
  686.           if (errno == EACCES) {
  687.         fprintf(stderr, catgets(elm_msg_cat, NewmailSet, NewmailErrNoPerm,
  688.               "\nPermission to monitor \"%s\" denied!\n\n"),
  689.              folders[current_folder].foldername);
  690.         exit(1);
  691.       }
  692.  
  693.     folders[current_folder].filesize = 
  694.           bytes(folders[current_folder].foldername);
  695.  
  696.     /* and finally let's output what we did */
  697.  
  698.       dprint(1, (debugfile, "folder %d: \"%s\" <%s> %s, size = %ld\n",
  699.           current_folder,
  700.           folders[current_folder].foldername,
  701.           folders[current_folder].prefix,
  702.           fd == NULL? "not found" : "opened",
  703.           folders[current_folder].filesize));
  704.  
  705.     if (fd != NULL) /* Close it only if we succeeded in opening it */
  706.         (void) fclose(fd);
  707.  
  708.     /* and increment current-folder please! */
  709.  
  710.     current_folder++;
  711.     total_folders++;
  712. }
  713.  
  714. add_default_folder()
  715. {
  716.     char    *cp;
  717.  
  718.     /* this routine will add the users home mailbox as the folder
  719.      * to monitor.  Since there'll only be one folder we'll never
  720.      * prefix it either...
  721.      *    determine mail file from environment variable if found,
  722.      *    else use password entry
  723.      */
  724.     if ((cp = getenv("MAIL")) == NULL)
  725.       sprintf(folders[0].foldername, "%s%s", mailhome, getusername());
  726.     else
  727.       strcpy(folders[0].foldername, cp);
  728.     
  729.     fd = fopen(folders[0].foldername, "r");
  730.     folders[0].filesize = bytes(folders[0].foldername);
  731.  
  732.     dprint(1, (debugfile, "default folder: \"%s\" <%s> %s, size = %ld\n",
  733.           folders[0].foldername,
  734.           folders[0].prefix,
  735.           fd == NULL? "not found" : "opened",
  736.           folders[0].filesize));
  737.  
  738.     total_folders = 1;
  739.     if (fd != NULL) /* Close it only if we succeeded in opening it */
  740.       fclose(fd);
  741. }
  742.  
  743.  
  744. forwarded(buffer, who)
  745. char *buffer, *who;
  746. {
  747.     /** change 'from' and date fields to reflect the ORIGINATOR of 
  748.         the message by iteratively parsing the >From fields...
  749.         The leading >From will already be stripped off the line. **/
  750.  
  751.     char machine[SLEN], buff[SLEN];
  752.  
  753.     machine[0] = '\0';
  754.     sscanf(buffer, "%s %*s %*s %*s %*s %*s %*s %*s %*s %s",
  755.                 who, machine);
  756.  
  757.     if(machine[0] == '\0')    /* try for address with timezone in date */
  758.     sscanf(buffer, "%s %*s %*s %*s %*s %*s %*s %*s %s",
  759.                 who, machine);
  760.  
  761.     if (machine[0] == '\0') /* try for srm address */
  762.       sscanf(buffer, "%s %*s %*s %*s %*s %*s %*s %s",
  763.                 who, machine);
  764.  
  765.     if (machine[0] == '\0')
  766.       sprintf(buff,"anonymous");
  767.     else
  768.       sprintf(buff,"%s!%s", machine, who);
  769.  
  770.     strncpy(who, buff, SLEN);
  771. }
  772.  
  773. show_header(hdr, cur_folder)
  774. struct header_rec *hdr;
  775. struct folder_struct *cur_folder;
  776. {
  777.     char from_line[SLEN];
  778.     char prefix[SLEN];
  779.     int used_to_line;
  780.  
  781.     if (hdr->from[0] == '\0')
  782.       strcpy(hdr->from, getusername());
  783.     if (hdr->subject[0] == '\0')
  784.       strcpy(hdr->subject, no_subj);
  785.     else {
  786.       used_to_line = strlen(hdr->subject) - 1;
  787.       if (hdr->subject[used_to_line] == '\n')
  788.         hdr->subject[used_to_line] = '\0'; /* strip off trailing new line, we add our own */
  789.     }
  790.  
  791.     used_to_line = tail_of(hdr->from, from_line, hdr->to);
  792.     prefix[0] = '\0';
  793.  
  794.     if (! in_window)
  795.       strcat(prefix, ">> ");
  796.  
  797.     if (print_prefix) {
  798.       strcat(prefix, cur_folder->prefix);
  799.       strcat(prefix, ": ");
  800.     }
  801.  
  802.     if (in_window) {
  803.       if (hdr->priority && used_to_line)
  804.         strcat(prefix, priority_to);
  805.       else if (hdr->priority)
  806.         strcat(prefix, priority_text);
  807.       else if (used_to_line)
  808.         strcat(prefix, To_text);
  809.       printf("\007%s%s -- %s\n", prefix, from_line, hdr->subject);
  810.     } else {
  811.       if (hdr->priority)
  812.         strcat(prefix, priority_mail);
  813.       else
  814.         strcat(prefix, mail_text);
  815.       if (used_to_line)
  816.         strcat(prefix, to_text);
  817.       else
  818.         strcat(prefix, from_text);
  819.       printf("\n\r%s%s - %s\n\r", prefix, from_line, hdr->subject);
  820.     }
  821. }
  822.  
  823. long
  824. bytes(name)
  825. char *name;
  826. {
  827.     /** return the number of bytes in the specified file.  This
  828.         is to check to see if new mail has arrived....  **/
  829.  
  830.     int ok = 1;
  831.     extern int errno;    /* system error number! */
  832.     struct stat buffer;
  833.  
  834.     if (stat(name, &buffer) != 0)
  835.       if (errno != 2) {
  836.         MCfprintf(stderr, catgets(elm_msg_cat, NewmailSet, NewmailErrFstat,
  837.           "Error %d attempting fstat on %s"), errno, name);
  838.         exit(1);
  839.       }
  840.       else
  841.         ok = 0;
  842.     
  843.     /* retain the access times for later use */
  844.  
  845. #if defined(BSD) && !defined(__convex__)
  846.         utime_buffer[0]     = buffer.st_atime;
  847.         utime_buffer[1]     = buffer.st_mtime;
  848. #else
  849.         utime_buffer.actime = buffer.st_atime;
  850.         utime_buffer.modtime= buffer.st_mtime;
  851. #endif
  852.  
  853.     return(ok ? buffer.st_size : 0);
  854. }
  855.  
  856. char  *getusername()
  857. {
  858.     /** Getting the username on some systems is a real pain, so...
  859.        This routine is guaranteed to return a usable username **/
  860.  
  861.     char *return_value, *getlogin(), *cuserid();
  862.  
  863.     if ((return_value = getlogin()) == NULL)
  864.       if ((return_value = cuserid(NULL)) == NULL) {
  865.         printf(catgets(elm_msg_cat, NewmailSet, NewmailErrUsername,
  866.           "Newmail: I can't get username!\n"));
  867.         exit(1);
  868.       }
  869.  
  870.     return( (char *) return_value);
  871. }
  872.  
  873. usage(name)
  874. char *name;
  875. {
  876.     /* print a nice friendly usage message */
  877.  
  878.     fprintf(stderr, catgets(elm_msg_cat, NewmailSet, NewmailArgsHelp1,
  879. "\nUsage: %s [-d] [-i interval] [-w] {folders}\n\
  880. \targ\t\t\tMeaning\n\r\
  881. \t -d  \tturns on debugging output\n\
  882. \t -i D\tsets the interval checking time to 'D' seconds\n\
  883. \t -w  \tforces 'window'-style output, and bypasses auto-background\n\n"),
  884.     name);
  885.  
  886.     fprintf(stderr, catgets(elm_msg_cat, NewmailSet, NewmailArgsHelp2,
  887. "folders can be specified by relative or absolute path names, can be the name\n\
  888. of a mailbox in the incoming mail directory to check, or can have one of the\n\
  889. standard Elm mail directory prefix chars (e.g. '+', '=' or '%%').\n\
  890. Furthermore, any folder can have '=string' as a suffix to indicate a folder\n\
  891. identifier other than the basename of the file\n\n"));
  892.  
  893. }
  894.  
  895.  
  896. expand_filename(name, store_space)
  897. char *name, *store_space;
  898. {
  899.     strcpy(store_space, name);
  900.     if (expand(store_space) == 0) {
  901.       fprintf(stderr, catgets(elm_msg_cat, NewmailSet, NewmailErrExpand,
  902.         "Sorry, but I couldn't expand \"%s\"\n"),name);
  903.       exit(1);
  904.     }
  905. }
  906.  
  907. pad_prefixes()
  908. {
  909.     /** This simple routine is to ensure that we have a nice
  910.         output format.  What it does is whip through the different
  911.         prefix strings we've been given, figures out the maximum
  912.         length, then space pads the other prefixes to match.
  913.     **/
  914.  
  915.     register int i, j, len = 0;
  916.  
  917.     for (i=0; i < total_folders; i++)
  918.       if (len < (j=strlen(folders[i].prefix)))
  919.         len = j;
  920.     
  921.     for (i=0; i < total_folders; i++)
  922.       for (j = strlen(folders[i].prefix); j < len; j++)
  923.         strcat(folders[i].prefix, " ");
  924. }
  925.